﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;

namespace SGCG.Model
{
    public static class AdaptativeDashing
    {
        // HACK Isto aqui é altamente non-thread-safe. Agasalha. (thread local storage poderia resolver, mas caguei)
        private static List<bool> computeToPaintCache;
        private static int computeToPaintCacheTotalLengthCondition;
        private static int computeToPaintDistanciaEntreTracejadosCondition;
        private static int computeToPaintTamanhoTracejadoCondition;
        public static List<bool> ComputeToPaint(int totalLength, int distanciaEntreTracejados, int tamanhoTracejado)
        {
            if (computeToPaintCache != null &&
                computeToPaintDistanciaEntreTracejadosCondition == distanciaEntreTracejados &&
                computeToPaintTamanhoTracejadoCondition == tamanhoTracejado &&
                computeToPaintCacheTotalLengthCondition == totalLength)
                return computeToPaintCache;

            int nextPerfectSize = (totalLength + 2 * distanciaEntreTracejados + tamanhoTracejado - 1) / (distanciaEntreTracejados + tamanhoTracejado) * (distanciaEntreTracejados + tamanhoTracejado) + tamanhoTracejado;
            List<bool> toPaint = new List<bool>(nextPerfectSize);
            for (int i = 0; i < nextPerfectSize; ++i)
                toPaint.Add(i % (distanciaEntreTracejados + tamanhoTracejado) < tamanhoTracejado);
            if (nextPerfectSize < totalLength)
                throw new Exception(); // HACK O que eu deveria fazer aqui? Debug.Assert?
            Random rng = new Random(totalLength * 31 + distanciaEntreTracejados * 37 + tamanhoTracejado * 71);
            while (toPaint.Count > totalLength)
            {
                int next = rng.Next(toPaint.Count);
                if (toPaint.Count > 2 && (next == 0 || next == toPaint.Count - 1))
                    continue;

                toPaint.RemoveAt(next);
            }

            computeToPaintDistanciaEntreTracejadosCondition = distanciaEntreTracejados;
            computeToPaintTamanhoTracejadoCondition = tamanhoTracejado;
            computeToPaintCacheTotalLengthCondition = totalLength;
            return computeToPaintCache = toPaint;
        }
    }
}
